package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.help.FineClueHelp;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.menu.ProMenuHelp;
import com.xbongbong.paas.model.FineClueCompanyModel;
import com.xbongbong.paas.model.FineClueUserModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.CommonFormListDTO;
import com.xbongbong.paas.pojo.dto.CommonFormSaveDTO;
import com.xbongbong.paas.pojo.vo.CommonFormListVO;
import com.xbongbong.paas.pojo.vo.CommonFormSaveVO;
import com.xbongbong.paas.service.CommonFormService;
import com.xbongbong.paas.service.FeeLogService;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.service.PaasMenuService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.constant.PackageConstant;
import com.xbongbong.pro.domain.entity.FineClueCompanyEntity;
import com.xbongbong.pro.domain.entity.FineClueUserEntity;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.FineClueEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.CRMMenuEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.menu.pojo.MenuReturnPojo;
import com.xbongbong.pro.menu.pojo.dto.CompanyCommonFormSaveDTO;
import com.xbongbong.pro.menu.pojo.dto.MenuNewListDTO;
import com.xbongbong.pro.menu.pojo.vo.AppMenuListVO;
import com.xbongbong.pro.menu.pojo.vo.CompanyCommonFormSaveVO;
import com.xbongbong.pro.menu.pojo.vo.MenuNewListVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.help.MarketManagementBusinessHelp;
import com.xbongbong.saas.service.toolbox.help.UpdatePackageRedisService;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.UserConfigEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.UserConfigEnum;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserConfigModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author: wufeng
 * @date: 2018/8/29 20:20
 * @desrcption:
 */
@Service("commonFormService")
public class CommonFormServiceImpl implements CommonFormService {

    private static final Logger LOG = LoggerFactory.getLogger(CommonFormServiceImpl.class);

    @Resource
    private UserConfigModel userConfigModel;

    @Resource
    private PaasMenuService paasMenuService;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private ProMenuHelp proMenuHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private UpdatePackageRedisService updatePackageRedisService;
    @Resource
    private MarketManagementBusinessHelp marketManagementBusinessHelp;
    @Resource
    private PaasAppService paasAppService;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private FineClueCompanyModel fineClueCompanyModel;
    @Resource
    private FineClueUserModel fineClueUserModel;
    @Resource
    private FineClueHelp fineClueHelp;
    @Resource
    private FeeLogService feeLogService;

    @Override
    public CommonFormListVO commonFormList(CommonFormListDTO commonFormListDTO) throws XbbException {
        CommonFormListVO commonFormListVO = new CommonFormListVO();
        try {
            MenuNewListDTO menuNewListDTO = new MenuNewListDTO();
            BeanUtil.copyProperties(commonFormListDTO, menuNewListDTO);
            MenuNewListVO menuNewListVO = new MenuNewListVO();
            List<MenuReturnPojo> commonFormList = paasMenuService.getCommonFormList(menuNewListDTO, menuNewListVO, true, true);
            Set<Long> idSet = new HashSet<>();
            if (Objects.nonNull(commonFormList)) {
                commonFormList.forEach(item->{
                    idSet.add(item.getMenuId());
                });
            }
            Map<String, Object> param = BeanUtil.convertBean2Map(commonFormListDTO, true);
            param.put("idIn", idSet);
            param.put("enable", 1);
            param.put("orderByStr", " sort ASC, update_time ASC ");
            // 经销商关闭后经销商相关表单隐藏
            Boolean distributorEnable = paasAppService.validateAppEnable(null, XbbRefTypeEnum.DISTRIBUTOR.getAlias(), SaasMarkEnum.SAAS.getCode(), menuNewListDTO.getCorpid());
            if (!distributorEnable) {
                param.put("distributorMark", DistributorMarkEnum.OTHER.getCode());
            }
            List<PaasMenuEntity> menuList = paasMenuModel.findEntitys(param);
            if (Objects.isNull(menuList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<AppMenuListVO> resultList = getMenuList(menuList, commonFormListDTO, commonFormList, 0);
            if (commonFormListDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.BUSINESS_CARD.getAlias())) {
                commonFormListVO.setBusinessCart(true);
            }
            //搜客过期 || 搜客应用关闭||无搜客坐席，去除常用表单中搜客子菜单
            PaasAppEntity appEntity = paasAppModel.getByAlias(ProPermissionAliasEnum.SOUKE.getAlias(), commonFormListDTO.getCorpid());
            FineClueCompanyEntity companyEntity = fineClueCompanyModel.getByCorpid(commonFormListDTO.getCorpid(), FineClueEnum.FINE_CLUE.getType());
            FineClueUserEntity clueUserEntity = fineClueUserModel.getByKey(commonFormListDTO.getCorpid(), commonFormListDTO.getUserId());
            if ((!fineClueHelp.fineClueUsable(commonFormListDTO.getCorpid(), FineClueEnum.FINE_CLUE)) || ((Objects.nonNull(appEntity) && (Objects.equals(appEntity.getEnable(), BasicConstant.ZERO)))) || ((Objects.nonNull(companyEntity)) && Objects.isNull(clueUserEntity))){
                List<String> souKeAlias = Arrays.asList(XbbRefTypeEnum.FINE_CLUE_QUERY_COMPANY.getAlias(),
                        XbbRefTypeEnum.FINE_CLUE_QUERY_CLUE.getAlias(),XbbRefTypeEnum.FINE_CLUE_MAP_QUERY.getAlias(),XbbRefTypeEnum.FINE_CLUE_BATCH_QUERY.getAlias());
                Iterator<AppMenuListVO> it = resultList.iterator();
                while (it.hasNext()){
                    AppMenuListVO appMenuListVO = it.next();
                    if (souKeAlias.contains(appMenuListVO.getAlias()) || Objects.equals(appMenuListVO.getAlias(), XbbRefTypeEnum.CONTRACT_COMPARE_RESULT.getAlias())){
                        it.remove();
                        break;
                    }
                }
            }
            commonFormListVO.setCommonFormList(resultList);
            commonFormListVO.setUserConfigId(menuNewListVO.getUserConfigId());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("commonForm数据库查询常用表单/报表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commonFormListVO;
    }


    @Override
    public CommonFormListVO quickNewList(CommonFormListDTO commonFormListDTO) throws XbbException {
        CommonFormListVO commonFormListVO = new CommonFormListVO();
        try {
            MenuNewListDTO menuNewListDTO = new MenuNewListDTO();
            BeanUtil.copyProperties(commonFormListDTO, menuNewListDTO);
            MenuNewListVO menuNewListVO = new MenuNewListVO();
            List<MenuReturnPojo> quickNewFormList = paasMenuService.getQuickNewFormList(menuNewListDTO, menuNewListVO, true, true);
            Set<Long> idSet = new HashSet<>();
            if (Objects.nonNull(quickNewFormList)) {
                quickNewFormList.forEach(item->{
                    idSet.add(item.getMenuId());
                });
            }
            Map<String, Object> param = BeanUtil.convertBean2Map(commonFormListDTO, true);
            param.put("idIn", idSet);
            param.put("enable", 1);
            List<PaasMenuEntity> menuList = paasMenuModel.findEntitys(param);
            if (Objects.isNull(menuList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<AppMenuListVO> resultList = getMenuList(menuList, commonFormListDTO, quickNewFormList, 1);
            commonFormListVO.setQuickNewList(resultList);
            commonFormListVO.setUserConfigId(menuNewListVO.getUserConfigId());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("commonForm数据库查询快捷新建出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commonFormListVO;
    }

    public List<AppMenuListVO> getMenuList(List<PaasMenuEntity> menuList, CommonFormListDTO commonFormListDTO, List<MenuReturnPojo> menuReturnList, Integer quickNew) throws XbbException{
        List<AppMenuListVO> resultList = new ArrayList<>();
        UserVO userVO = commonFormListDTO.getLoginUser();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Boolean isAdminOrBoss = userVO.isAdminOrBoss();
        Set<String> permissionAlias = userVO.getPermSet();
        Map<Long, MenuReturnPojo> menuReturnMap = new HashMap<>(menuReturnList.size());
        menuReturnList.forEach(item->{
            menuReturnMap.put(item.getMenuId(), item);
        });
        String corpid = commonFormListDTO.getCorpid();
        Integer num = updatePackageRedisService.getUnusedNumPackageLimit(corpid, ValueAddedTypeEnum.CUSTOM_FORM_NUM);
        //根据套餐获取当前公司套餐不能看到的菜单
        List<String> unSeeMenuList = packageHelp.getUnSeeMenuList(corpid);
        PaasFormEntity paasFormEntity = paasFormModel.getByBusinessType(XbbRefTypeEnum.COMMUNICATE_PLAN.getCode(), corpid);
        for (PaasMenuEntity item : menuList) {
            // 移动端不展示客户对账单
            if (Objects.equals(PlatFormEnum.DINGTALK.getValue(), commonFormListDTO.getPlatform()) && Objects.equals(XbbRefTypeEnum.CUSTOMER_STATEMENT.getAlias(), item.getAlias())) {
                continue;
            }
            if (Objects.equals(quickNew, 1)) {
                Boolean hasPermission = proMenuHelp.validateAddPermission(userVO, item);
                if (!userVO.isAdminOrBoss() && !hasPermission) {
                    continue;
                }
            } else {
                String alias = item.getAlias();
                Boolean hasPermission = proMenuHelp.validateViewPermission(userVO, alias, item.getSaasMark(), item.getId());
                if (!userVO.isAdminOrBoss()
                        && !hasPermission) {
                    continue;
                }
            }
            //市场管理应用未开启的话，过滤掉市场活动和线索的菜单
            if(!marketManagementBusinessHelp.isEnableWithApp(corpid) && XbbRefTypeEnum.checkMarketManagementBusinessType(item.getAlias())){
                continue;
            }
            if (unSeeMenuList.contains(item.getAlias())) {
                continue;
            }
            AppMenuListVO appMenuListVO = new AppMenuListVO();
            BeanUtil.copyProperties(item, appMenuListVO);
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByAlias(item.getAlias());
            MenuReturnPojo menuReturnPojo = menuReturnMap.get(item.getId());
            appMenuListVO.setSort(menuReturnPojo.getSort());
            appMenuListVO.setBusinessType(xbbRefTypeEnum.getCode());
            String url = appMenuListVO.getUrl();
            String mobileUrl = appMenuListVO.getMobileUrl();

            if (MenuTypeEnum.getFormList().contains(item.getType()) && Objects.equals(SaasMarkEnum.SAAS.getCode(), item.getSaasMark())) {
                String sourceName = I18nMessageUtil.getMessage(xbbRefTypeEnum.getI18nName(), Locale.CHINA);
                appMenuListVO.setSourceName(sourceName);
            } else {
                appMenuListVO.setSourceName(item.getName());
            }
            Boolean adminSignIn = isAdminOrBoss || permissionAlias.contains(ProPermissionAliasEnum.SIGN_IN_STATISTIC.getAlias());
            // 数据库中存了访客计划地址，前端要固定
            if (CRMMenuEnum.COMMUNICATE_PLAN.getAlias().equals(appMenuListVO.getAlias())){
                mobileUrl = AccessLinkEnum.COMMUNICATE_PLAN.getMobileUrl();
            }
            if (adminSignIn && CRMMenuEnum.SIGN_IN.getAlias().equals(appMenuListVO.getAlias())) {
                url = AccessLinkEnum.ADMIN_SIGN_IN.getUrl();
                mobileUrl = AccessLinkEnum.ADMIN_SIGN_IN.getMobileUrl();
            } else if (isAdminOrBoss && CRMMenuEnum.COMMUNICATE_PLAN.getAlias().equals(appMenuListVO.getAlias())) {
                url = AccessLinkEnum.ADMIN_COMMUNICATE_PLAN.getUrl();
                mobileUrl = AccessLinkEnum.ADMIN_COMMUNICATE_PLAN.getMobileUrl();
                appMenuListVO.setIsAdminCommunicatePlan(true);
            }
            StringBuilder stringBuilder = new StringBuilder(url)
                    .append("?subBusinessType=").append(xbbRefTypeEnum.getCode())
                    .append("&appId=").append(appMenuListVO.getAppId())
                    .append("&menuId=").append(appMenuListVO.getId())
                    .append("&saasMark=").append(appMenuListVO.getSaasMark());
            appMenuListVO.setUrl(stringBuilder.toString());
            StringBuilder mobileUrlStr = new StringBuilder(mobileUrl)
                    .append("?subBusinessType=").append(xbbRefTypeEnum.getCode())
                    .append("&appId=").append(appMenuListVO.getAppId())
                    .append("&menuId=").append(appMenuListVO.getId())
                    .append("&saasMark=").append(appMenuListVO.getSaasMark());
            // 访客计划，获取表单信息
            if (CRMMenuEnum.COMMUNICATE_PLAN.getAlias().equals(appMenuListVO.getAlias()) && Objects.equals(quickNew, 0)) {
                if (Objects.nonNull(paasFormEntity)) {
                    mobileUrlStr.append("&formId=").append(paasFormEntity.getId())
                            .append("&businessType=").append(XbbRefTypeEnum.COMMUNICATE_PLAN.getCode())
                            .append("&idAdminOrBoss=").append(userVO.isAdminOrBoss());
                }
            }
            if (Objects.equals(SaasMarkEnum.PAAS.getCode(), item.getSaasMark()) && num > 0) {
                appMenuListVO.setPackageLimit(1);
                appMenuListVO.setMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.CUSTOM_FORM_SIZE_MESSAGE), num));
            }
            appMenuListVO.setMobileUrl(mobileUrlStr.toString());
            resultList.add(appMenuListVO);

        }
        if (!resultList.isEmpty()) {
            Collections.sort(resultList, new Comparator<AppMenuListVO>() {
                @Override
                public int compare(AppMenuListVO o1, AppMenuListVO o2) {
                    //升序
                    return o1.getSort() - o2.getSort();
                }
            });
        }
        return resultList;
    }

    @Override
    public CommonFormSaveVO save(CommonFormSaveDTO commonFormSaveDTO) throws XbbException {
        CommonFormSaveVO commonFormSaveVO = new CommonFormSaveVO();
        try {
            Long userConfigId = commonFormSaveDTO.getUserConfigId();
            String corpid = commonFormSaveDTO.getCorpid();
            if (Objects.isNull(userConfigId)) {
                UserConfigEntity userConfigEntity = userConfigModel.getByUserId(commonFormSaveDTO.getUserId(), corpid, UserConfigEnum.COMMON_FORM.getAlias());
                if (Objects.nonNull(userConfigEntity)) {
                    userConfigId = userConfigEntity.getId();
                }
            }
            List<MenuReturnPojo> menuReturnList = getMenuConfigList(commonFormSaveDTO.getFormList());

            if(userConfigId == null) {
                UserConfigEntity userConfigEntity = new UserConfigEntity();
                BeanUtils.copyProperties(commonFormSaveDTO, userConfigEntity);
                userConfigEntity.setConfigValue(JSONObject.toJSONString(menuReturnList));
                String configAlias = UserConfigEnum.COMMON_FORM.getAlias();
                String configName = UserConfigEnum.COMMON_FORM.getName();
                userConfigEntity.setConfigAlias(configAlias);
                userConfigEntity.setConfigName(configName);
                userConfigModel.insert(userConfigEntity);

                commonFormSaveVO.setUserConfigId(userConfigEntity.getId());
            } else {
                UserConfigEntity userConfigEntity = userConfigModel.getByKey(userConfigId, corpid);
                if (userConfigEntity == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.CONFIG_NOT_EXIST);
                }
                UserConfigEntity entity = new UserConfigEntity();
                BeanUtils.copyProperties(commonFormSaveDTO, entity);
                entity.setConfigValue(JSONObject.toJSONString(menuReturnList));
                entity.setId(userConfigId);
                userConfigModel.update(entity);
                commonFormSaveVO.setUserConfigId(userConfigId);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("commonForm.save数据库设置常用表单/报表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commonFormSaveVO;
    }

    @Override
    public CompanyCommonFormSaveVO companyCommonFormSave(CompanyCommonFormSaveDTO companyCommonFormSaveDTO) throws XbbException{
        CompanyCommonFormSaveVO companyCommonFormSaveVO = new CompanyCommonFormSaveVO();
        try {
            String configAlias = UserConfigEnum.COMMON_FORM.getAlias();
            String corpid = companyCommonFormSaveDTO.getCorpid();
            CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(configAlias, corpid);

            List<MenuReturnPojo> menuReturnList = getMenuConfigList(companyCommonFormSaveDTO.getMenuList());

            if(companyCommonFormSaveDTO.getConfigId() == null && Objects.isNull(companyConfigEntity)) {
                CompanyConfigEntity insertCompanyConfigEntity = new CompanyConfigEntity();
                BeanUtils.copyProperties(companyCommonFormSaveDTO, insertCompanyConfigEntity);
                String configName = UserConfigEnum.COMMON_FORM.getName();
                insertCompanyConfigEntity.setConfigName(configName);

                insertCompanyConfigEntity.setConfigAlias(configAlias);
                insertCompanyConfigEntity.setConfigValue(JSONObject.toJSONString(menuReturnList));
                companyConfigModel.insert(insertCompanyConfigEntity);
                companyCommonFormSaveVO.setUserConfigId(insertCompanyConfigEntity.getId());
            } else {
                Long key = companyConfigEntity.getId();
                CompanyConfigEntity entity = new CompanyConfigEntity();
                BeanUtils.copyProperties(companyCommonFormSaveDTO, entity);
                entity.setConfigValue(JSONObject.toJSONString(menuReturnList));
                entity.setId(key);
                companyConfigModel.update(entity);
                companyCommonFormSaveVO.setUserConfigId(key);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("commonForm.companyCommonFormSave数据库设置公司常用表单/报表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return companyCommonFormSaveVO;
    }

    private List<MenuReturnPojo> getMenuConfigList(List<Long> menuIdIn) throws XbbException {
        List<MenuReturnPojo> menuReturnList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(menuIdIn.size());
        param.put("idIn", menuIdIn);
        param.put("del", DelEnum.NORMAL.getDel());
        List<PaasMenuEntity> menuList = paasMenuModel.findEntitys(param);
        if (Objects.isNull(menuList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        Map<Long, PaasMenuEntity> menuMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasMenuEntity item : menuList) {
           menuMap.put(item.getId(), item);
        }
        for (int i = 0; i < menuIdIn.size(); i++) {
            PaasMenuEntity paasMenuEntity = menuMap.get(menuIdIn.get(i));
            MenuReturnPojo menuReturnPojo = new MenuReturnPojo();
            BeanUtil.copyProperties(paasMenuEntity, menuReturnPojo);
            menuReturnPojo.setMenuId(paasMenuEntity.getId());
            menuReturnPojo.setSort(i);
            menuReturnList.add(menuReturnPojo);
        }
        return menuReturnList;
    }
}
